package com.baofu.paycore.service.processor.recharge;

import com.baofu.clear.service.facade.enums.EventTypeEnum;
import com.baofu.paycore.biz.external.clear.EventService;
import com.baofu.paycore.biz.external.clear.model.EventRuleResBO;
import com.baofu.paycore.common.enums.FundTypeEnum;
import com.baofu.paycore.service.facade.enums.PayCoreErrorCode;
import com.baofu.paycore.common.utils.Constant;
import com.baofu.paycore.service.facade.enums.PayStatusEnums;
import com.baofu.paycore.manager.model.RechargeBO;
import com.baofu.paycore.manager.model.RechargeFundBO;
import com.baofu.paycore.service.facade.model.FundBaseDTO;
import com.baofu.paycore.service.facade.model.recharge.RechargeDTO;
import com.baofu.paycore.service.processor.PayBaseProcessor;
import com.system.commons.exception.BizServiceException;
import com.system.commons.sequence.redis.SequenceFacade;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 充值资金单处理类
 *
 * <p/>
 *      1、构建支付属性
 * </p>
 * User: LZQ Date: 2016/04/20  Version: 1.0
 */
@Slf4j
@Component
public class RechargeFundProcessor implements PayBaseProcessor<RechargeBO, RechargeDTO> {

    /**
     * 资金明细单号生成
     */
    @Autowired
    private SequenceFacade sequenceFacade;

    /**
     * 会计事件服务
     */
    @Autowired
    private EventService eventService;

    /**
     * 构建支付属性
     *
     * @param rechargeBO      支付模型
     * @param rechargeDTO     请求参数
     */
    @Override
    public PayBaseProcessor process(RechargeBO rechargeBO, RechargeDTO rechargeDTO) {
        assembleRechargeFund(rechargeBO, rechargeDTO);
        return this;
    }

    /**
     * 组装资金渠道
     *
     * @param rechargeBO   充值BO对象
     * @param rechargeDTO  充值DTO对象
     */
    private void assembleRechargeFund(RechargeBO rechargeBO, RechargeDTO rechargeDTO){

        List<RechargeFundBO> rechargeFundBOs = new ArrayList<>();
        FundBaseDTO fundBaseDTO = rechargeDTO.getFundBaseDTO();
        RechargeFundBO rechargeFundByAcc = new RechargeFundBO();
        this.buildRechargeFundBO(fundBaseDTO.getAmt(), rechargeDTO, rechargeFundByAcc, rechargeBO.getPayNo(),
                FundTypeEnum.RECHARGE, 1);
        rechargeFundBOs.add(rechargeFundByAcc);
        if (Constant.validateLong(fundBaseDTO.getBizChargeAmount())>0){
            String eventNo = eventProcessor(rechargeDTO);
            RechargeFundBO rechargeFundByFee = new RechargeFundBO();
            this.buildRechargeFundBO(fundBaseDTO.getBizChargeAmount(), rechargeDTO, rechargeFundByFee,
                    rechargeBO.getPayNo(), FundTypeEnum.FEE,0);
            rechargeFundByFee.setEventNo(eventNo);
            rechargeFundBOs.add(rechargeFundByFee);
        }
        rechargeBO.setRechargeFundBO(rechargeFundBOs);
    }

    private void buildRechargeFundBO(Long reqAccAmt, RechargeDTO rechargeDTO,RechargeFundBO rechargeFundBO,
                                     String payNo, FundTypeEnum typeEnum, int sort){
        FundBaseDTO fundBaseDTO = rechargeDTO.getFundBaseDTO();
        //资金明细No
        rechargeFundBO.setFundDetailNo(sequenceFacade.getUniqueSeq());
        rechargeFundBO.setStatus(PayStatusEnums.INIT.getCode());
        rechargeFundBO.setAccountNo(rechargeDTO.getAccountNo());
        rechargeFundBO.setPayToolType(fundBaseDTO.getPayToolType());
        rechargeFundBO.setPayToolSubType(fundBaseDTO.getPayToolSubType());
        rechargeFundBO.setAmt(fundBaseDTO.getAmt());
        rechargeFundBO.setCcy(fundBaseDTO.getCcy());
        rechargeFundBO.setAgreeRelId(rechargeDTO.getFundBaseDTO().getAgreeRelId());
        rechargeFundBO.setAgreementNo(rechargeDTO.getFundBaseDTO().getAgreementNo());
        rechargeFundBO.setBizFeeAccount(rechargeDTO.getFundBaseDTO().getBizFeeAccount());
        rechargeFundBO.setReqAccAmt(reqAccAmt);
        rechargeFundBO.setPayNo(payNo);
        rechargeFundBO.setFundType(typeEnum);
        rechargeFundBO.setSort(sort);
    }

    /**
     * 获取手续费会计事件号
     *
     * @param rechargeDTO   请求参数
     * @return              会计事件号
     */
    private String eventProcessor(RechargeDTO rechargeDTO) {
        EventRuleResBO ruleResBO = eventService.queryEventNo(EventTypeEnum.FEE, rechargeDTO.getSubBizType());
        if (!PayStatusEnums.SUCCESS.getCode().equals(ruleResBO.getStatus())) {
            log.error("产品大类:{}, 产品细类:{}", rechargeDTO.getBizType(), rechargeDTO.getSubBizType());
            throw new BizServiceException(PayCoreErrorCode.EVENT_NO_NOT_EXIST);
        }

        return ruleResBO.getEventNo();
    }
}
